# coding = utf-8
import datetime

from django.db import transaction
from django.db.models import Q, F, Sum
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet

from finance.api.serializers import CapitalAccountSerializer, FundBillSerializer, RepaymentBillSerializer, \
    JournalSerializer, PrepaymentSerializer, AccountSerializer
from finance.api.utils import update_account, increase_account_amount
from finance.models import CapitalAccount, FundBill, RepaymentBill, Journal, Prepayment


class PrepaymentListAPIView(APIView):
    """资金账号"""
    # authentication_classes = ()
    permission_classes = ()
    pagination_class = None

    def get(self, request, *args, **kwargs):
        customer_id = request.query_params.get("customer")
        if not customer_id:
            return Response({"return_code": -1})

        result = Prepayment.objects.filter(customer_id=int(customer_id))\
            .aggregate(total_amount=Sum('amount'), total_deduct=Sum('deduct_amount'))
        amount = result.get('total_amount') or 0
        deduct_amount = result.get('total_deduct') or 0
        amount -= deduct_amount
        if amount == 0:
            return Response({"return_code": -1})
        obj = Prepayment.objects.filter(customer_id=int(customer_id), flag=0).order_by('-order_time').first()
        data = {
            "return_code": 0,
            'code': obj.customer.name + '预收款',
            'order_time': datetime.datetime.now().date(),
            'customer_name': obj.customer.name,
            'saler_name': obj.user.real_name if obj.user else '',
            'total_amount': amount * -1,
            'amount': 0,
            'norecv_amount': amount * -1,
            'flag_name': '预收款',
            'remark': '预收款支付',
            'category': 1
        }
        return Response(data)


class CapitalAccountListAPIView(ListAPIView):
    """资金账号"""
    permission_classes = ()
    pagination_class = None
    queryset = CapitalAccount.objects.all()
    serializer_class = AccountSerializer


class CapitalAccountViewSet(ModelViewSet):
    """资金账号"""
    permission_classes = ()
    queryset = CapitalAccount.objects.all()
    serializer_class = CapitalAccountSerializer

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

        self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)


class FundBillViewSet(ModelViewSet):
    """资金账单"""
    # authentication_classes = ()
    permission_classes = ()
    queryset = FundBill.objects.all()
    serializer_class = FundBillSerializer

    def get_queryset(self):
        queryset = super().get_queryset()
        name = self.request.query_params.get("name", None)
        category = self.request.query_params.get("category", None)

        search_date = self.request.query_params.getlist("search_date[]", None)

        if category:
            queryset = queryset.filter(category=int(category))

        if name:
            queryset = queryset.filter(Q(employee__name__contains=name) | Q(order_no__contains=name))
        # 时间
        if search_date and len(search_date) == 2:
            queryset = queryset.filter(order_time__range=(search_date[0], search_date[1]))
        return queryset

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                if instance.verify == 1:
                    self.update_account(instance)
                self.perform_destroy(instance)
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['get'], detail=False)
    def user_bills(self, request, *args, **kwargs):
        category = request.query_params.get("category", None)
        employee = request.query_params.get("employee", None)
        if category and employee:
            queryset = self.get_queryset().filter(category=int(category), employee_id=int(employee), money__gt=F("repayment"))

            serializer = self.get_serializer(instance=queryset, many=True)

            return Response(data=serializer.data, status=status.HTTP_200_OK)
        else:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "查询失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

    def update_account(self, obj):
        if obj.category == 0 or obj.category == 3:
            if obj.money != obj.repayment:
                update_account(obj.account_id, (obj.money - obj.repayment) * -1)
        elif obj.category == 1 or obj.category == 2:
            if obj.money != obj.get_repayment():
                update_account(obj.account_id, obj.money - obj.get_repayment())


class RepaymentBillViewSet(ModelViewSet):
    """还款记录"""
    # authentication_classes = ()
    permission_classes = ()
    queryset = RepaymentBill.objects.all()
    serializer_class = RepaymentBillSerializer

    def create(self, request, *args, **kwargs):
        if isinstance(request.data, list):  # 批量增加
            serializer = self.get_serializer(data=request.data, many=True)
        else:
            serializer = self.get_serializer(data=request.data)

        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                account_id = instance.bill.account_id
                money = instance.money * -1 if instance.bill.category == 2 else instance.money
                update_account(account_id, money)
                self.perform_destroy(instance)
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        return Response(status=status.HTTP_204_NO_CONTENT)


class JournalViewSet(ModelViewSet):
    """流水账"""
    # authentication_classes = ()
    permission_classes = ()
    pagination_class = None
    queryset = Journal.objects.all()
    serializer_class = JournalSerializer

    def get_queryset(self):
        queryset = super().get_queryset()

        order_no = self.request.query_params.get("order_no", None)
        customer_id = self.request.query_params.get("customer", None)
        account_id = self.request.query_params.get("account", None)
        search_date = self.request.query_params.getlist("search_date[]", None)

        if order_no:
            queryset = queryset.filter(Q(name__contains=order_no) | Q(order_no__contains=order_no))

        if account_id:
            queryset = queryset.filter(account_id=int(account_id))

        if customer_id:
            queryset = queryset.filter(customer_id=int(customer_id))

        if search_date and len(search_date) == 2:
            queryset = queryset.filter(order_time__date__range=(search_date[0], search_date[1]))

        return queryset

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

        self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)


class PrepaymentViewSet(ModelViewSet):
    """预付款"""
    permission_classes = ()
    queryset = Prepayment.objects.all()
    serializer_class = PrepaymentSerializer

    def get_queryset(self):
        queryset = super().get_queryset()

        name = self.request.query_params.get("name", None)
        search_date = self.request.query_params.getlist("search_date[]", None)
        # customer_id = self.request.query_params.get("supplier", None)
        # user_id = self.request.query_params.get("user", None)

        if search_date and len(search_date) == 2:
            queryset = queryset.filter(order_time__range=(search_date[0], search_date[1]))

        if name:
            queryset = queryset.filter(customer__name__contains=name)

        return queryset

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                increase_account_amount(instance.account_id, -1 * instance.amount, instance.customer_id)
                self.perform_destroy(instance)
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['delete'], detail=False)
    def batch_delete(self, request, *args, **kwargs):
        select_ids = request.data.get("select_ids", None)
        if not select_ids:
            msg = {"status_code": status.HTTP_404_NOT_FOUND, "message": "删除失败!"}
            return Response(data=msg, status=status.HTTP_404_NOT_FOUND)

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                self.update_account(select_ids)
                self.serializer_class.Meta.model.objects.filter(id__in=select_ids).delete()
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(save_id)

            transaction.savepoint_commit(save_id)

        msg = {"status_code": status.HTTP_204_NO_CONTENT, "message": "删除成功!"}
        return Response(data=msg, status=status.HTTP_204_NO_CONTENT)

    def update_account(self, ids):
        objs = self.serializer_class.Meta.model.objects.filter(id__in=ids)
        for obj in objs:
            increase_account_amount(obj.account_id, -1 * obj.amount, obj.customer_id)
